<?php

class BaseObject_model extends CI_Model {
	var $dbName = "default";
	var $tableName;
	var $primary_key = 'id';
	var $columns;
	var $defaultCols;
	var $defaultOrder;
	var $search_options = array();
	var $joinstrs = array();
	
	function __construct() {
		parent::__construct();
	}

	function getColumns($cols=null) {
		if(empty($cols) || $cols=='*') {
			if(isset($this->defaultCols)){
				$cols = explode(',',$this->defaultCols);
			}else{
				$cols = array_keys($this->columns);
			}
		} else {
			$cols = explode(',',$cols);
		}

		$colDef = array();
		foreach($cols as $col) {
			$col =trim($col);
			if(!isset($this->columns[$col])) continue;

			$def = $this->columns[$col];
			if(! (isset($def['type']) && $def['type'] == 'dynamic' )){
				$colDef[$col] = $def;
			}
		}

		return $colDef;
	}

	function getFilterColumns($cols=null){
		if(!$cols){
			$cols = array_keys($this->columns);			
		}else{
			$cols = explode(',',$cols);
		}
		$colDef = array();
		foreach($cols as $col) {
			if(!isset($this->columns[$col])) continue;

			$def = $this->columns[$col];
			if(isset($def['isfilter']) && !$def['isfilter']){
				continue;
			}else if(isset($def['type']) && $def['type'] == 'dynamic' ){
				continue;
			}
			$colDef[$col] = $def;
		}
		return $colDef;
	}

	function _buildCols($colDef) {
		$find = false;
		$cols = array_keys($colDef);
		foreach($cols as &$col) {
			if($col == $this->primary_key) {
				$find = true;
			}
			$col = $this->consummateCol($col);
		}

		if(!$find) {
			$cols[] = $this->consummateCol($this->primary_key);
		}
		return implode(',',$cols);
	}

	function _filter($filter) {
		if(!$filter) return;

		foreach($filter as $f) {
			if(!is_array($f)){
				//TODO throw Exception
				continue;
			}
			if(count($f)!=3) {
				//TODO throw Exception
				continue;
			}
			
			$op = $f[0];
			$field  = $this->consummateCol($f[1]);
			$value = $f[2];

			switch($op) {
				case '=':
					$this->db->where($field,$value);
					break;
				case '!=':
					$this->db->where($field.' !=',$value);
					break;
				case '>':
					$this->db->where($field.' >',$value);
					break;
				case '<':
					$this->db->where($field.' <',$value);
					break;
				case '>=':
					$this->db->where($field.' >=',$value);
					break;
				case '<=':
					$this->db->where($field.' <=',$value);
					break;
				case 'LIKE':
					$this->db->like($field,$value);
					break;
				case 'IN':
					$this->db->where_in($field,$value);
					break;
				case 'IS NOT NULL':
					$this->db->where($field.' IS NOT NULL',$value);
					break;
			}
		}
	}
	
	function _from($filter ,$colDefs=array()){
		if($filter){
			foreach($filter as $f) {
				if( ! is_array($f) || count($f)!=3){
					continue;
				}
				if(isset($this->columns[$f[1]])){
					$colDefs[] = $this->columns[$f[1]];
				}
			}
		}
		$jstrs = array();
		foreach($colDefs as $def){
			if( ! isset($def['table'])){
				continue;
			}
			$tables = explode(':' , $def['table']);
			foreach($tables as $table){
				$jstrs[$table] = $this->joinstrs[$table];
			}
		}
		$this->db->from($this->tableName);
		foreach($jstrs as $table=>$join){
			$this->db->join($table , $join , 'left' );
		}
		if( ! empty($jstrs)){
			return true;
		}
		return false;
	}

	function _orderBy($orderby){
		if(empty($orderby) && isset($this->defaultOrder)){
			$orderby = $this->defaultOrder;
		}
		if(empty($orderby)) {
			return;
		}
		foreach($orderby as $k => $v) {
			if( ! isset($this->columns[$k]) ) {
				continue;
			}
			if( isset($this->columns[$k]['type']) && $this->columns[$k]['type'] == 'dynamic' ) {
				continue;
			}
			$this->db->order_by($this->consummateCol($k),$v);
		}
	}
	
	function consummateCol($col){
		if(stripos($col , '.')){
			return 	$col;
		}
		if( ! isset($this->columns[$col])){
			return $this->tableName.'.'.$col;
		}
		$def = $this->columns[$col];
		if( ! isset($def['table'])){
			return $this->tableName.'.'.$col;
		}
		$tables = explode(':' , $def['table']);
		if(empty($tables)){
			return $this->tableName.'.'.$col;
		}
		$dtable = end($tables);
		$table = end(explode('.' , $dtable));
		return $table.'.'.$col;
	}
	
	function pageQuery($cols,$filter,$pageno=1,$pagesize=20,$orderby=null,$disabledCols=null,$editMode=false) {
		if($pagesize>500) $pagesize = 500;

		$colDef = $this->getColumns($cols);
		$cols = $this->_buildCols($colDef);
		$totalCount = $this->findCount($filter);
		$totalPage = intval($totalCount%$pagesize)==0?intval($totalCount/$pagesize):(intval($totalCount/$pagesize)+1);
		$start = ($pageno-1)*$pagesize;
		
		if($totalCount < $start) {
			$pageno = $totalPage < 1 ? 1 : $totalPage;
			$start = ($pageno-1)*$pagesize;
		}

		$this->load->database($this->dbName);
		$this->db->select($cols);
		
		$ismulti = $this->_from($filter , $colDef);
		/*XXX fuck here
		if($ismulti){
			$this->db->distinct();
		}*/

		$this->_filter($filter);

		$this->_orderby($orderby);
		
		$this->db->limit($pagesize,$start);
		$query = $this->db->get();
		$result = $query->result_array();
		$query->free_result();

		if($this->primary_key != 'id') {
			foreach($result as &$row) {
				$row['id'] = $row[$this->primary_key];
			}
		}
		
		foreach($colDef as $colName =>$def) {
			if(isset($def['modifier'])) {
				$func = 'modifier_'.$def['modifier'];
			} else {
				$func = 'modifier_'.$colName;
			}
			if(method_exists($this,$func)) {
				$this->$func($colName,$result,$colDef);
			}
		}
		//echo $this->db->last_query();
		$itemPage = array(
			'totalCount'=>$totalCount,
			'totalPage'=>$totalPage,
			'pageno'=>$pageno,
			'pagesize'=>$pagesize,
			'colDef'=>$colDef,
			'records'=>$result,
			'query'=>$this->db->last_query()
		);
		return $itemPage;
	}

	function findCount($filter) {
		$cnt = 0;
		$this->load->database($this->dbName);
		$this->db->cache_on();
		//多表连接查询的结果可能会有重复数据 ， count时候采用distinct主键可以避免
		$ismulti = $this->_from($filter);
		if($ismulti){
			$this->db->select('count(distinct '.$this->consummateCol($this->primary_key).') as cnt');
		}else{
			$this->db->select('count(*) as cnt');
		}
		$this->_filter($filter);
//		$cnt = $this->db->count_all_results();
		$query = $this->db->get();
		$result = $query->row_array();
		$query->free_result();
		$cnt = $result['cnt'];
		$this->db->cache_off();
//		echo $this->db->last_query();
//		echo '<br>';
		return $cnt;
	}


	function modifier_row($col,&$rows,&$colDef) {
	}

	function modifier_money($col,&$rows,&$colDef) {
		foreach($rows as &$row) {
			$row[$col] = number_format($row[$col], 2, '.', '');
		}
	}
	
	function findByPrimaryKey($primary_key, $filed = '*'){
		$db = $this->load->database($this->dbName, TRUE);
		$db->select($filed);
		$db->from($this->tableName);
		$db->where($this->primary_key , $primary_key);
		$query = $db->get();
		$result = $query->row_array();
		$query->free_result();
		return $result;
	}
	
	
	
	function update($primary_key, $data){
		if(!is_array($data)){
			return false;
		}
		$db = $this->load->database($this->dbName, TRUE);
		unset($data[$this->primary_key]);
		$db->where($this->primary_key , $primary_key);
		$ret = $db->update($this->tableName , $data);
		return $ret;
	}
	
	function insert($data){
		$db = $this->load->database($this->dbName, TRUE);
		$db->insert($this->tableName, $data);
		return ($db->affected_rows() == 1) ? $db->insert_id() : 0;
	}

	function delete($ids){
		$db = $this->load->database($this->dbName, TRUE);
		if(is_array($ids)){
			$db->where_in($this->primary_key, $ids);
		}else{
			$db->where($this->primary_key, $ids);		
		}
		$ret = $db->delete($this->tableName);
		return $ret;
	}
	
	function disable($ids){
		$db = $this->load->database($this->dbName, TRUE);
		if(is_array($ids)){
			$db->where_in($this->primary_key, $ids);
		}else{
			$db->where($this->primary_key, $ids);	
		}
		return $db->update($this->tableName,array('disabled'=>'true'));
	}
	
	function active($ids){
		$db = $this->load->database($this->dbName, TRUE);
		$count = 1;
		if(is_array($ids)){
			$db->where_in($this->primary_key, $ids);
			$count = count($ids);
		}else{
			$db->where($this->primary_key, $ids);
		}
		return $db->update($this->tableName,array('disabled'=>"false"));
	}
}
?>
